#ifndef __BGI_H
#define __BGI_H

#include "types.h"

enum graphics_errors
{
  grOk                  =   0,
  grNoInitGraph         =  -1,
  grNotDetected         =  -2,
  grFileNotFound        =  -3,
  grInvalidDriver       =  -4,
  grNoLoadMem           =  -5,
  grNoScanMem           =  -6,
  grNoFloodMem          =  -7,
  grFontNotFound        =  -8,
  grNoFontMem           =  -9,
  grInvalidMode         = -10,
  grError               = -11,   /* generic error */
  grIOerror             = -12,
  grInvalidFont         = -13,
  grInvalidFontNum      = -14,
  grInvalidDeviceNum    = -15,
  grInvalidVersion      = -18
};

enum FontOrient
{
  fntNormalOrient       = 0,
  fntVerticalOrient     = 1,
  fntDownOrient         = 2,
  fntVerticalDownOrient = 3
};

typedef struct
{
  uint8_t  status;
  uint8_t  type;
  uint16_t xres;
  uint16_t yres;
  uint16_t xefres;
  uint16_t yefres;
  uint16_t xinch;
  uint16_t yinch;
  uint16_t aspect;
  uint8_t  chsizex;
  uint8_t  chsizey;
  uint8_t  fcolors;
  uint8_t  bcolors;
} BGIStatus_t;

typedef int16_t coord_t;
typedef uint8_t color_t;

typedef struct
{
  coord_t x, y;
} point_t;

typedef struct
{
  color_t fore, fill;
} color_param_t;

typedef struct
{
  coord_t x1, y1, x2, y2;
} rect_t;

typedef struct
{
  uint8_t style[8];
} FillStyle_t;

typedef struct
{
  uint8_t number;
  uint8_t orientation;
} FontDescr_t;

typedef uint8_t CharImage_t[8];

typedef struct
{
  uint8_t red;
  uint8_t green;
  uint8_t blue;
} RGBPaletteEntry_t;

extern RGBPaletteEntry_t __based(__segname("_CODE")) DefaultRGBPalette[256];

extern BGIStatus_t  status;
extern point_t      cp;
extern rect_t       vp;

extern CharImage_t _far *font8x8;

#ifdef __cplusplus
extern "C" {
#endif

BGIStatus_t _far *InstallDriver(uint8_t ModeNo);
#pragma aux InstallDriver parm [CX] value [ES BX]

uint16_t ModeQuery(void);
#pragma aux ModeQuery value [CX]

void const _far *ModeName(uint16_t ModeNo);
#pragma aux ModeName parm [CX] value [ES BX]

void Init(struct DIT _far *p);
#pragma aux Init parm [ES BX]

void Clear(void);
/* no #pragma aux needed */

void Post(void);
/* no #pragma aux needed */

void Move(coord_t x, coord_t y);
#pragma aux Move parm [AX] [BX]

void Draw(coord_t x, coord_t y);
#pragma aux Draw parm [AX] [BX]

void Vect(coord_t x1, coord_t y1, coord_t x2, coord_t y2);
#pragma aux Vect parm [AX] [BX] [CX] [DX]

void PatBar(coord_t x1, coord_t y1, coord_t x2, coord_t y2);
#pragma aux PatBar parm [AX] [BX] [CX] [DX]

/*
PALETTE -> Load a color entry into the Palette
ALLPALETTE -> Load the full palette
COLOR -> Load the current drawing color.
*/

void Color(color_param_t colors);
#pragma aux Color parm [AX]

void setFillStyle(uint8_t pattern, FillStyle_t _far *userPattern);
#pragma aux setFillStyle parm [AX] [ES BX]

void setLineStyle(uint8_t Pat, uint16_t UserPat, uint16_t LineWidth);
#pragma aux setLineStyle parm [AX] [BX] [CX]

uint32_t setTextStyle(FontDescr_t fd, int xSize, int ySize);
#pragma aux setTextStyle parm [AX] [BX] [CX] value [CX BX]

void Text(unsigned char _far *string, int len);
#pragma aux Text parm [ES BX] [CX]

uint32_t getTextSize(char const _far *string, size_t len);
#pragma aux getTextSize parm [ES BX] [CX] value [CX BX]

void FloodFill(coord_t x, coord_t y, color_t color);
#pragma aux FloodFill parm [AX] [BX] [CX]

color_t GetPixel(coord_t x, coord_t y);
#pragma aux GetPixel parm [AX] [BX] value [DL]

typedef void PUT_PIXEL_FUNC(coord_t x, coord_t y, color_t color);
#pragma aux PUT_PIXEL_FUNC parm [AX] [BX] [DX]

void    PutPixel(coord_t x, coord_t y, color_t color);
#pragma aux (PutPixel, PUT_PIXEL_FUNC)

/*
BITMAPUTIL -> Bitmap Utilities Function Table
*/

void setDrawPage(uint8_t page);
#pragma aux setDrawPage parm [AX]

void setVisualPage(uint8_t page);
#pragma aux setVisualPage parm [AX]

void setWriteMode(uint16_t mode);
#pragma aux setWriteMode parm [AX]

void SaveBitmap(coord_t x1, coord_t y1, struct Bitmap_t _far *p);
#pragma aux SaveBitmap parm [CX] [DX] [ES BX]

void RestoreBitmap(coord_t x1, coord_t y1, uint8_t mode, struct Bitmap_t _far *p);
#pragma aux RestoreBitmap parm [CX] [DX] [AX] [ES BX]

void Clip(coord_t x1, coord_t y1, coord_t x2, coord_t y2);
#pragma aux Clip parm [AX] [BX] [CX] [DX]

/*
COLOR_QUERY -> Device Color Information Query
*/

/* HELPER/INTERNAL/STILL WRAPPED FUNCTIONS */
color_t getDrawColor(bool_t draw);
color_t getFillColor(bool_t draw);
color_t getBkgrColor(void);
void    setBkgrColor(color_t bkgr);
#pragma aux setBkgrColor parm [AX]

void    PatBarLine(coord_t y, coord_t x1, coord_t x2);
void    initFont(void);

void    XorPutPixel(coord_t x, coord_t y, color_t color);
#pragma aux(XorPutPixel, PUT_PIXEL_FUNC)

void    OrPutPixel(coord_t x, coord_t y, color_t color);
#pragma aux(OrPutPixel, PUT_PIXEL_FUNC)

void    AndPutPixel(coord_t x, coord_t y, color_t color);
#pragma aux(AndPutPixel, PUT_PIXEL_FUNC)

void    NotPutPixel(coord_t x, coord_t y, color_t color);
#pragma aux(NotPutPixel, PUT_PIXEL_FUNC)

typedef PUT_PIXEL_FUNC *PutPixelFuncPtr_t;

PutPixelFuncPtr_t GetPutPixelFunc(uint16_t mode);

extern PutPixelFuncPtr_t PutPixelFunc;

#ifdef __cplusplus
} // extern "C"
#endif

#endif // __BGI_H
